Skip to content

feat(aws-strands): add strands typescript sdk integration#1681

Open
cogwirrel wants to merge 2 commits into
ag-ui-protocol:mainfrom
cogwirrel:feat/strands-ts
Open

feat(aws-strands): add strands typescript sdk integration#1681
cogwirrel wants to merge 2 commits into
ag-ui-protocol:mainfrom
cogwirrel:feat/strands-ts

Conversation

@cogwirrel
Copy link
Copy Markdown

Adds a TypeScript adapter under integrations/aws-strands/typescript that mirrors the existing Python adapter as much as possible.

Provides:

  • StrandsAgent wrapping a Strands Agent or multi-agent orchestrator (Graph/Swarm) and translating its streaming events into AG-UI events (text, reasoning, tool calls, tool results, state snapshots, messages snapshots, multi-agent steps, custom events).
  • StrandsAgentConfig / ToolBehavior with camelCase equivalents of every Python hook (stateFromArgs, stateFromResult, customResultHandler, argsStreamer, predictState, sessionManagerProvider, ...).
  • Express transport via addStrandsExpressEndpoint + createStrandsApp, plus addPing and addCapabilities for health + advertised-event matrix.
  • Eight runnable examples matching the Python server (agentic-chat, agentic-chat-reasoning, agentic-chat-multimodal, backend-tool-rendering, shared-state, agentic-generative-ui, human-in-the-loop) plus a TS-only tool-based-generative-ui example, and a dojo server that mounts all eight at the Python reference paths.
  • Injectable Logger (config.logger) with Python-parity debug traces.

Native interrupt bridge (Strands SDK 1.1.0+):

  • AgentResult.stopReason === "interrupt" emits RUN_FINISHED with outcome.type "interrupt" and the outstanding interrupts; IDs are recorded per thread.
  • RunAgentInput.resume[] is validated against pending IDs (interrupts.mdx rule 4) and converted into Strands InterruptResponseContent[] forwarded as the stream args. Unknown IDs short-circuit with UNKNOWN_INTERRUPT.

Key differences vs. the Python adapter:

SDK-forced (behavior unchanged):

  • Typed .type dispatch instead of Python's dict-key matching.
  • AgentConfig.messages seeding at construction time vs. Python's in-place self.messages mutation; drives a separate buildStrandsSeed helper.
  • Hardcoded TemplateAgentCloneFields in place of Python's inspect.signature introspection of StrandsAgentCore.init.

Additive (TS-only, close conformance gaps or match TS ecosystem):

  • Multi-agent orchestrator mode for Strands Graph/Swarm.
  • THREAD_BUSY guard for concurrent runs on the same thread.
  • AbortController wired into Strands cancelSignal so client disconnects cancel the underlying stream.
  • Native Strands interrupt bridge (above).
  • HTTP-edge request validation (415 / 400) via the shared Zod RunAgentInputSchema, with snake_case -> camelCase key normalization.
  • HTTP/1.1 + HTTP/2 disconnect handling that fires iterator.return() so the generator's finally runs (releases THREAD_BUSY slot, aborts stream).
  • Explicit protobuf content negotiation (no binary frames for Accept: /).
  • GET /capabilities endpoint advertising supported events/features.
  • emitChunkEvents collapsing _START/_CONTENT/*_END triples into self-expanding TEXT/TOOL_CALL/REASONING chunks.
  • ToolCallContextExtras exposing context[] + forwardedProps on every hook context and stateContextBuilder.

Dojo wiring:

  • aws-strands-typescript entry in agents.ts, menu.ts, env.ts, the prep/run scripts, and the dojo-e2e.yml CI matrix (port 8022).
  • Feature list is a strict superset of the Python sibling: agentic_chat, agentic_chat_reasoning, agentic_chat_multimodal, v1_agentic_chat, backend_tool_rendering, agentic_generative_ui, shared_state, human_in_the_loop, tool_based_generative_ui.

Closes #1680

Adds a TypeScript adapter under integrations/aws-strands/typescript that
mirrors the existing Python adapter as much as possible.

Provides:
- StrandsAgent wrapping a Strands Agent or multi-agent orchestrator
  (Graph/Swarm) and translating its streaming events into AG-UI events
  (text, reasoning, tool calls, tool results, state snapshots, messages
  snapshots, multi-agent steps, custom events).
- StrandsAgentConfig / ToolBehavior with camelCase equivalents of every
  Python hook (stateFromArgs, stateFromResult, customResultHandler,
  argsStreamer, predictState, sessionManagerProvider, ...).
- Express transport via addStrandsExpressEndpoint + createStrandsApp,
  plus addPing and addCapabilities for health + advertised-event matrix.
- Eight runnable examples matching the Python server (agentic-chat,
  agentic-chat-reasoning, agentic-chat-multimodal, backend-tool-rendering,
  shared-state, agentic-generative-ui, human-in-the-loop) plus a TS-only
  tool-based-generative-ui example, and a dojo server that mounts all
  eight at the Python reference paths.
- Injectable Logger (config.logger) with Python-parity debug traces.

Native interrupt bridge (Strands SDK 1.1.0+):
- AgentResult.stopReason === "interrupt" emits RUN_FINISHED with
  outcome.type "interrupt" and the outstanding interrupts; IDs are
  recorded per thread.
- RunAgentInput.resume[] is validated against pending IDs (interrupts.mdx
  rule 4) and converted into Strands InterruptResponseContent[] forwarded
  as the stream args. Unknown IDs short-circuit with UNKNOWN_INTERRUPT.

Key differences vs. the Python adapter:

SDK-forced (behavior unchanged):
- Typed .type dispatch instead of Python's dict-key matching.
- AgentConfig.messages seeding at construction time vs. Python's in-place
  self.messages mutation; drives a separate buildStrandsSeed helper.
- Hardcoded TemplateAgentCloneFields in place of Python's
  inspect.signature introspection of StrandsAgentCore.__init__.

Additive (TS-only, close conformance gaps or match TS ecosystem):
- Multi-agent orchestrator mode for Strands Graph/Swarm.
- THREAD_BUSY guard for concurrent runs on the same thread.
- AbortController wired into Strands cancelSignal so client disconnects
  cancel the underlying stream.
- Native Strands interrupt bridge (above).
- HTTP-edge request validation (415 / 400) via the shared Zod
  RunAgentInputSchema, with snake_case -> camelCase key normalization.
- HTTP/1.1 + HTTP/2 disconnect handling that fires iterator.return() so
  the generator's finally runs (releases THREAD_BUSY slot, aborts stream).
- Explicit protobuf content negotiation (no binary frames for Accept: */*).
- GET /capabilities endpoint advertising supported events/features.
- emitChunkEvents collapsing *_START/*_CONTENT/*_END triples into
  self-expanding TEXT/TOOL_CALL/REASONING chunks.
- ToolCallContextExtras exposing context[] + forwardedProps on every
  hook context and stateContextBuilder.

Dojo wiring:
- aws-strands-typescript entry in agents.ts, menu.ts, env.ts, the prep/run
  scripts, and the dojo-e2e.yml CI matrix (port 8022).
- Feature list is a strict superset of the Python sibling: agentic_chat,
  agentic_chat_reasoning, agentic_chat_multimodal, v1_agentic_chat,
  backend_tool_rendering, agentic_generative_ui, shared_state,
  human_in_the_loop, tool_based_generative_ui.

Closes ag-ui-protocol#1680
@cogwirrel cogwirrel requested a review from a team as a code owner May 14, 2026 14:38
@vercel
Copy link
Copy Markdown

vercel Bot commented May 14, 2026

@cogwirrel is attempting to deploy a commit to the CopilotKit Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 20, 2026

Python Preview Packages

Version 0.0.0.dev1779288518 published to TestPyPI.

Warning: These packages are built from contributor code that may not yet have been vetted for correctness or security. Install at your own risk and do not use in production.

Install with uv

Add the TestPyPI index to your pyproject.toml:

[[tool.uv.index]]
name = "testpypi"
url = "https://test.pypi.org/simple/"
explicit = true

Then install the packages you need:

# Core SDK
uv add 'ag-ui-protocol==0.0.0.dev1779288518' --index testpypi

# Integrations (each already depends on the matching ag-ui-protocol preview)
uv add 'ag-ui-langgraph==0.0.0.dev1779288518' --index testpypi
uv add 'ag-ui-crewai==0.0.0.dev1779288518' --index testpypi
# NOTE: ag-ui-agent-spec depends on pyagentspec (git-only, not on PyPI).
# You will need to install pyagentspec separately from its git repo.
uv add 'ag-ui-agent-spec==0.0.0.dev1779288518' --index testpypi
uv add 'ag_ui_adk==0.0.0.dev1779288518' --index testpypi
uv add 'ag_ui_strands==0.0.0.dev1779288518' --index testpypi

Install with pip

pip install \
  --index-url https://test.pypi.org/simple/ \
  --extra-index-url https://pypi.org/simple/ \
  ag-ui-protocol==0.0.0.dev1779288518

Use --extra-index-url https://pypi.org/simple/ so pip can resolve
transitive dependencies (pydantic, fastapi, etc.) from real PyPI.


Commit: 8a18fe7

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 20, 2026

Open in StackBlitz

@ag-ui/a2a-middleware

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/a2a-middleware@1681

@ag-ui/a2ui-middleware

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/a2ui-middleware@1681

@ag-ui/event-throttle-middleware

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/event-throttle-middleware@1681

@ag-ui/mcp-apps-middleware

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/mcp-apps-middleware@1681

@ag-ui/middleware-starter

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/middleware-starter@1681

@ag-ui/a2a

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/a2a@1681

@ag-ui/adk

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/adk@1681

@ag-ui/ag2

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/ag2@1681

@ag-ui/agno

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/agno@1681

@ag-ui/aws-strands

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/aws-strands@1681

@ag-ui/claude-agent-sdk

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/claude-agent-sdk@1681

@ag-ui/crewai

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/crewai@1681

@ag-ui/langchain

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/langchain@1681

@ag-ui/langgraph

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/langgraph@1681

@ag-ui/langroid

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/langroid@1681

@ag-ui/llamaindex

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/llamaindex@1681

@ag-ui/mastra

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/mastra@1681

@ag-ui/pydantic-ai

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/pydantic-ai@1681

@ag-ui/server-starter

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/server-starter@1681

@ag-ui/server-starter-all-features

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/server-starter-all-features@1681

@ag-ui/vercel-ai-sdk

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/vercel-ai-sdk@1681

@ag-ui/watsonx

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/watsonx@1681

create-ag-ui-app

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/create-ag-ui-app@1681

@ag-ui/client

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/client@1681

@ag-ui/core

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/core@1681

@ag-ui/encoder

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/encoder@1681

@ag-ui/proto

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/proto@1681

commit: 65139a8

@ranst91
Copy link
Copy Markdown
Contributor

ranst91 commented May 20, 2026

Overall looking great!

Several things that came up on manual testing:

  1. The server starts on 8002 but dojo expects 8022
  2. When running human in the loop demo. Followup doesn't end up in agent context, also the actual provided plan isn't. What I mean by this is, the UI is rendered and you get to pick some steps. Once picked and approved, the agent message coming up next should be a direct result of what was picked. Currently it just lists the steps, and even then it doesn't list the same steps as in the UI it generated.
  3. When using "agentic generative UI" all text messages that are emitted after the UI rendering, actually show before it. I guess it's a bug on when are things emitted or so
  4. "Tool based generative UI" demo doesn't work, getting: block_type= | reasoning content is not yet supported in multi-turn conversations with the responses api
  5. Shared state - Currently it doesn't seem to be streaming the state as things are being added, but rather there's a wait and then the whole thing is shown to the screen in 1 bulk

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: [AWS Strands] Support for TypeScript

2 participants